﻿using System;
using System.Xml.Linq;
using System.Xml.Schema;
using System.IO;
using System.Collections.Generic;
using Microsoft.VisualStudio.SharePoint;
using Microsoft.VisualStudio.Shell;
using System.Xml;
using System.Net;

namespace CodeCounsel.SharePoint.RibbonDesigner.Model
{
    public static class Schema
    {
        class SharePointSchemaResolver
            : XmlResolver
        {
            ISharePointProjectService _projectService;

            public SharePointSchemaResolver(ISharePointProjectService projectService)
            {
                _projectService = projectService;
            }

            public override ICredentials Credentials
            {
                set {  }
            }

            public override object GetEntity(Uri absoluteUri, 
                string role, Type ofObjectToReturn)
            {
                string localPath = absoluteUri.LocalPath;
                string schemaFileName = Path.GetFileName(localPath);
                return Schema.LoadSharePointSchema(_projectService, schemaFileName);
            }
        }

        public const string Id = "Id";
        public const string LabelText = "LabelText";
        public const string Image16by16 = "Image16by16";
        public const string Image32by32 = "Image32by32";
        public const string Image16by16Top = "Image16by16Top";
        public const string Image32by32Top = "Image32by32Top";
        public const string Image16by16Left = "Image16by16Left";
        public const string Image32by32Left = "Image32by32Left";
        public const string Title = "Title";
        public const string LayoutTitle = "LayoutTitle";
        public const string TemplateAlias = "TemplateAlias";
        public const string DisplayMode = "DisplayMode";
        public const string DividerAfter = "DividerAfter";
        public const string DividerBefore = "DividerBefore";
        public const string Type = "Type";
        public const string Alignment = "Alignment";
        public const string Description = "Description";
        public const string CssClass = "CssClass";
        public const string Sequence = "Sequence";
        public const string Command = "Command";
        public const string Size = "Size";
        public const string GroupId = "GroupId";
        public const string Template = "Template";
        public const string Location = "Location";

        static XmlSchemaSet _schemas;

        static Schema()
        {
            ISharePointProjectService projectService = (ISharePointProjectService)Package.GetGlobalService(typeof(ISharePointProjectService));
            _schemas = new XmlSchemaSet();
            _schemas.XmlResolver = new SharePointSchemaResolver(projectService);
            _schemas.Add(LoadSharePointSchema(projectService, "wss.xsd"));
            _schemas.Compile();
        }

        static XmlSchema LoadSharePointSchema(
            ISharePointProjectService projectService, string schemaFile)
        {
            XmlSchema schema = null;
            using (StreamReader reader = File.OpenText(
                 Path.Combine(projectService.SharePointInstallPath,
                 @"TEMPLATE\XML",
                 schemaFile)))
            {
                schema = XmlSchema.Read(reader, null);
            }
            return schema;
        }

        public static bool Validate(XDocument document)
        {
            if (document == null || document.Root == null)
            {
                return true;
            }
            bool isValid = false;
            try
            {
                document.Validate(_schemas, null, true);
                isValid = true;
            }
            catch (XmlSchemaValidationException)
            {
            }
            return isValid;
        }

        internal static bool Validate(XElement element)
        {
            bool isValid = false;
            try
            {
                IXmlSchemaInfo schemaInfo = element.GetSchemaInfo();
                if (schemaInfo == null)
                {
                    if (element.Parent != null)
                    {
                        Validate(element.Parent);
                    }
                }
                else if (schemaInfo.Validity != XmlSchemaValidity.Valid)
                {
                    element.Validate(schemaInfo.SchemaElement, _schemas, null);
                }
            }
            catch (XmlSchemaValidationException)
            {
            }
            return isValid;
        }
    }
}
